package com.czmh.etc.onlinepubsys.feign.WeiXin;

import com.czmh.etc.onlinepubsys.feign.WeiXin.entity.WeiXinAccessTokenResponse;
import com.czmh.etc.onlinepubsys.feign.WeiXin.entity.WeiXinUserInfoResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * Created by HuangYK(Administrator) on 2019/10/16.
 * 微信开放文档地址:
 * https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
 *
 */
@FeignClient(name = "WeiXinClient",
        url = "https://api.weixin.qq.com/cgi-bin",
        configuration = WeiXinConfig.class,
        fallback = WeiXinClient.DefaultFallback.class
)
public interface WeiXinClient {
    public static String LANG_ZH_CN = "zh_CN";
    public static String LANG_ZH_TW = "zh_TW";
    public static String LANG_EN = "en";

    /**
     * 根据传入的公众号accessToken和用户的openid, 获取到用户与公众号的关系及用户信息!
     * @param accessToken 不可为空!调用接口凭证!
     * @param openId 不可为空!普通用户的标识，对当前公众号唯一!
     * @param lang 可为空, 返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语
     * @return
     */
    @RequestMapping(value = "/user/info", method = RequestMethod.GET)
    WeiXinUserInfoResponse getUserInfoByAccessToken(@RequestParam("access_token") String accessToken,
                                                    @RequestParam("openid") String openId,
                                                    @RequestParam("lang") String lang);

    /**
     * access_token是公众号的全局唯一接口调用凭据，公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。
       access_token的有效期目前为2个小时，需定时刷新，重复获取将导致上次获取的access_token失效。
     * 公众平台的API调用所需的access_token的使用及生成方式说明：
     * 1、建议公众号开发者使用中控服务器统一获取和刷新access_token，其他业务逻辑服务器所使用的access_token均来自于该中控服务器，
          不应该各自去刷新，否则容易造成冲突，导致access_token覆盖而影响业务；
     * 2、目前access_token的有效期通过返回的expire_in来传达，目前是7200秒之内的值。中控服务器需要根据这个有效时间提前去刷新新access_token。
          在刷新过程中，中控服务器可对外继续输出的老access_token，此时公众平台后台会保证在5分钟内，新老access_token都可用，这保证了第三方业务的平滑过渡；
     * 3、access_token的有效时间可能会在未来有调整，所以中控服务器不仅需要内部定时主动刷新，还需要提供被动刷新access_token的接口，
          这样便于业务服务器在API调用获知access_token已超时的情况下，可以触发access_token的刷新流程。
     * 公众号和小程序均可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在“微信公众平台-开发-基本配置”页中获得（需要已经成为开发者，且帐号没有异常状态）。
     * **调用接口时，请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中，点击查看设置方法，否则将无法调用成功。**小程序无需配置IP白名单。
     * @param grantType 不可为空! 获取access_token填写client_credential
     * @param appid 不可为空! 第三方用户唯一凭证
     * @param appsecret 不可为空! 第三方用户唯一凭证密钥，即appsecret
     * @return
     */
    @RequestMapping(value = "/token", method = RequestMethod.GET)
    WeiXinAccessTokenResponse getAccessTokenByAppid(@RequestParam("grant_type") String grantType,
                                                    @RequestParam("appid") String appid,
                                                    @RequestParam("secret") String appsecret);

    @Slf4j
    public class DefaultFallback implements WeiXinClient {

        @Override
        public WeiXinUserInfoResponse getUserInfoByAccessToken(@RequestParam("access_token") String accessToken, @RequestParam("openid") String openId, @RequestParam("lang") String lang) {
            return null;
        }

        @Override
        public WeiXinAccessTokenResponse getAccessTokenByAppid(@RequestParam("grant_type") String grantType,
                                                               @RequestParam("appid") String appid,
                                                               @RequestParam("secret") String appsecret) {
            return null;
        }
    }
}
